package com.goodfather.textbook.youdao.pad.util;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.text.TextUtils;

import androidx.annotation.Nullable;

import com.goodfather.textbook.youdao.pad.bean.Sentence;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;


public class MediaPlayerService extends Service implements AudioManager.OnAudioFocusChangeListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
    public static final int MSG_REGISTER_CLIENT = 0x01;
    public static final int MSG_UNREGISTER_CLIENT = 0x02;


    public static final int MSG_PLAYER_START = 0x10;
    public static final int MSG_PLAYER_PAUSE = 0x11;
    public static final int MSG_PLAY_SENTENCE = 0x12;
    public static final int MSG_CANCEL_SENTENCE = 0x13;

    public static final int MSG_ON_PLAYER_START = 0x14;
    public static final int MSG_ON_PLAYER_PAUSE = 0x15;
    public static final int MSG_ON_SENTENCE_PLAY_BEGIN = 0x16;
    public static final int MSG_ON_SENTENCE_PLAY_END = 0x17;
    public static final int MSG_ON_SENTENCE_CANCEL = 0x18;
    public static final int MSG_ON_DURATION = 0x20;
    public static final int MSG_ON_AUDIO_ID = 0x21;
    public static final int MSG_ON_AUDIO_ERROR = 0x22;
    public static final int MSG_ON_AUDIO_PREPARE = 0x23;
    public static final String PUBLISHING_ID = "PUBLISHING_ID";
    public static final String BOOK_ID = "BOOK_ID";

    ArrayList<Messenger> mClients = new ArrayList<>();
    private Timer mTimer;
    private MediaPlayer mMediaPlayer;
    private boolean autoPlay;
    private int startPoint = -1;
    private int endPoint = -1;
    private Sentence currentSentence;
    private TimerTask mPlayEndTask;
    private String mCurrentUrl;
    private AudioManager mAudioManager;
    private String mBookId;
    private String mPublishingId;
    private boolean isChangeRes;

    @Override
    public void onAudioFocusChange(int focusChange) {
        switch (focusChange) {
            case AudioManager.AUDIOFOCUS_GAIN:
                L.d("AUDIO_FOCUS_GAIN");
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                L.d("AUDIO_FOCUS_LOSS_TRANSIENT");
                break;
        }
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        if (mp != null) {
            int duration = mp.getDuration();
            L.d("duration:" + duration);
            sendMessageToClients(MSG_ON_DURATION, duration);
            sendMessageToClients(MSG_ON_AUDIO_PREPARE, true);
            if (isChangeRes && startPoint >= 0) {
                isChangeRes = false;
                setStartPoint(startPoint, true);
            }
        }
    }

    @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {

    }

    @Override
    public void onSeekComplete(MediaPlayer mp) {
        L.d("onSeekComplete");
        if (autoPlay) {
            if (startPoint >= 0) {
                if (mTimer == null) {
                    mTimer = new Timer("timer", false);
                }
                mTimer.purge();
                mPlayEndTask = new TimerTask() {
                    @Override
                    public void run() {
                        onPlayEnd();
                    }
                };
                if (endPoint == 0) {
                    endPoint = mp.getDuration();
                }
                int delay = endPoint - startPoint;
                if ((delay > 0)) {
                    sendMessageToClients(MSG_ON_PLAYER_START, true);
                    mTimer.schedule(mPlayEndTask, delay);
                    mp.start();
                }
                L.d("onSeekComplete----delay:" + delay);

            }
        }
        if (mp != null) {
            int duration = mp.getDuration();
            sendMessageToClients(MSG_ON_DURATION, duration);
        }
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        L.d("onCompletion");
        onPlayEnd();
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        L.d("onError---" + what + "/" + extra);
//        mp.reset();
//        cancelSentence();
        sendMessageToClients(MSG_ON_AUDIO_ERROR, null);
        return true;
    }

    /**
     * handler of incoming messages from clients;
     */
    private class InComingHandler extends Handler {

        private final WeakReference<MediaPlayerService> mService;

        public InComingHandler(MediaPlayerService service) {
            mService = new WeakReference<>(service);
        }

        @Override
        public void handleMessage(Message msg) {
            MediaPlayerService service = mService.get();
            switch (msg.what) {
                case MSG_REGISTER_CLIENT:
                    mClients.add(msg.replyTo);
                    break;
                case MSG_UNREGISTER_CLIENT:
                    mClients.remove(msg.replyTo);
                    break;
                case MSG_PLAY_SENTENCE:
                    if (msg.obj instanceof Sentence) {
                        Sentence sentence = (Sentence) msg.obj;
                        service.playSentence(sentence);
                    }
                    break;
                case MSG_CANCEL_SENTENCE:
                    cancelSentence();
                    break;
                case MSG_PLAYER_START:
                    startPlay();
                    break;
                case MSG_PLAYER_PAUSE:
                    pausePlay();
                    break;
            }
            super.handleMessage(msg);
        }
    }

    final Messenger mServiceMessenger = new Messenger(new InComingHandler(this));

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mServiceMessenger.getBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        initMediaPlayer();
        mTimer = new Timer("timer", false);
        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);

    }

    public MediaPlayer initMediaPlayer() {
        if (mMediaPlayer == null) {
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setOnBufferingUpdateListener(this);
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setOnErrorListener(this);
            mMediaPlayer.setOnSeekCompleteListener(this);
            mMediaPlayer.setOnCompletionListener(this);
        }

        return mMediaPlayer;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            mBookId = intent.getStringExtra(BOOK_ID);
            mPublishingId = intent.getStringExtra(PUBLISHING_ID);
        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        if (mMediaPlayer != null) {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        if (mTimer != null) {
            mTimer.cancel();
            mTimer.purge();
        }
        if (mAudioManager != null) {
            mAudioManager.abandonAudioFocus(this);
        }

    }

    private void playSentence(Sentence sentence) {
        if (TextUtils.isEmpty(sentence.beginTime) || TextUtils.isEmpty(sentence.endTime)) {
            return;
        }
        currentSentence = sentence;
        float begin;
        float end;

        try {
            begin = Float.valueOf(sentence.beginTime);
        } catch (NumberFormatException e) {
            begin = -1;
            e.printStackTrace();
        }

        try {
            end = Float.valueOf(sentence.endTime);
        } catch (NumberFormatException e) {
            end = -1;
            e.printStackTrace();
        }

        int startPoint = (int) (begin * 1000);
        int endPoint = (int) (end * 1000);
        this.startPoint = startPoint;
        this.endPoint = endPoint;
        if (startPoint >= 0) {
            L.d("playSentence---" + sentence.sentenceId + "|" + startPoint + "<->" + endPoint + "|" + (endPoint - startPoint));
            if (currentSentence != null) {
//                String fileName = sentence.audioUrl.substring(sentence.audioUrl.lastIndexOf("/") + 1);
//                String path = mPublishingId + mBookId + File.separator + fileName;
                setMP3InUrl(sentence.audioUrl);
//                if (BookUtil.hasMP3FileInFiles(C.get(), path)) {
//                    setMP3InFiles(path);
//                } else {
//                    setMP3InUrl(sentence.audioUrl);
//                }
                sendMessageToClients(MSG_ON_SENTENCE_PLAY_BEGIN, currentSentence);
            }
            setStartPoint(startPoint, true);
        }
    }

    private void setMP3InUrl(String audioUrl) {
        if (TextUtils.isEmpty(audioUrl)) return;
        if (!audioUrl.equals(mCurrentUrl)) {
            sendMessageToClients(MSG_ON_AUDIO_ID, currentSentence.lessonId);
            try {
                mMediaPlayer.reset();
                mMediaPlayer.setDataSource(audioUrl);
                mMediaPlayer.setLooping(false);
                mMediaPlayer.prepareAsync();
                mCurrentUrl = audioUrl;
            } catch (IOException e) {
                e.printStackTrace();
            }
            isChangeRes = true;
        } else {
            isChangeRes = false;
        }
    }

    private void setMP3InFiles(String cache) {
        if (!cache.equals(mCurrentUrl)) {
            File parentFile = StorageUtils.getIndividualCacheDirectory
                    (C.get());
            File cacheFile = new File(parentFile, cache);
            if (cacheFile.exists() && cacheFile.length() > 0) {
                sendMessageToClients(MSG_ON_AUDIO_ID, currentSentence.lessonId);
                try {
                    FileInputStream fis = new FileInputStream(cacheFile);
                    mMediaPlayer.reset();
                    mMediaPlayer.setDataSource(fis.getFD());
                    mMediaPlayer.prepareAsync();
                    this.mCurrentUrl = cache;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                }
            }
            isChangeRes = true;
        } else {
            isChangeRes = false;
        }
    }

    private void setStartPoint(int start, boolean autoPlay) {
        L.d("setStartPoint---" + start + "|" + autoPlay);
        if (mMediaPlayer != null && start >= 0) {
            this.autoPlay = autoPlay;
            if (isChangeRes) {
//                mMediaPlayer.start();
            } else {
                mMediaPlayer.seekTo(start);
            }
        }
    }

    private void cancelSentence() {
        if (mPlayEndTask != null) {
            mPlayEndTask.cancel();
            mPlayEndTask = null;
        }

        if (mTimer != null) {
            mTimer.cancel();
            mTimer = null;
        }

        startPoint = -1;
        endPoint = -1;

        if (mMediaPlayer != null) {
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
                if (currentSentence != null) {
                    sendMessageToClients(MSG_ON_SENTENCE_CANCEL, currentSentence);

                }
            }
        }
    }

    private void onPlayEnd() {
        try {
            if (mMediaPlayer != null) {
                L.d("onSentencePlayEnd");
                if (mMediaPlayer.isPlaying()) {
                    mMediaPlayer.pause();
                }
                startPoint = -1;
                endPoint = -1;
                sendMessageToClients(MSG_ON_SENTENCE_PLAY_END, currentSentence);
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

    private void pausePlay() {
        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
            mMediaPlayer.pause();
            sendMessageToClients(MSG_ON_PLAYER_PAUSE, false);
        }
    }

    private void startPlay() {
        if (mMediaPlayer != null && !mMediaPlayer.isPlaying()) {
            mMediaPlayer.start();
            sendMessageToClients(MSG_ON_PLAYER_START, false);
        }
    }

    private void sendMessageToClients(int type, Object obj) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                Message msg = Message.obtain(null, type);
                if (obj != null) {
                    msg.obj = obj;
                }
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                mClients.remove(i);
                e.printStackTrace();
            }
        }
    }

}
